package com.evolved.automata.examples.sudoku;
import java.util.*;

import com.evolved.automata.*;
import com.evolved.automata.algorithms.interruptible.*;
import com.evolved.automata.filetools.*;

public class SudokuAction implements ChoicePointer {
	private LinkedList[][] j_BoardDefinition;
	private IntPair j_CellToModify;
	private BoardTransform j_ActionUndoBoardTransform;
	private Integer j_SetValue;
	public SudokuBoard j_SudokuBoard;
    private BoardUtilities j_Utilities;

	public SudokuAction(SudokuBoard board, int row, int column, Integer value)
	{
		j_SudokuBoard=board;
		j_CellToModify = new IntPair(row,column);
		j_SetValue=value;
		j_BoardDefinition=board.GetDefinition();
		j_Utilities=board.GetUtilities();
	}
	
	public int GetRow()
	{
		return j_CellToModify.GetFirst();
		
	}
	
	public int GetColumn()
	{
		return j_CellToModify.GetSecond();
	}
	
	public int GetValue()
	{
		return j_SetValue.intValue();
	}
	public ChoiceNode ResolveNode(){
		
		// Remove all values not the current value from current cell
		LinkedList<Integer> valuesRemovedFromCurrentCell = new LinkedList<Integer>();
		int row = j_CellToModify.GetFirst();
		int column=j_CellToModify.GetSecond();
		
		LinkedList<Integer> possibleValues = j_BoardDefinition[row][column];
		LinkedList<Integer> newValues = new LinkedList<Integer>();
		newValues.add(j_SetValue);
		for (Integer valueToRemove:possibleValues)
		{
			if (!valueToRemove.equals(j_SetValue))
				valuesRemovedFromCurrentCell.add(valueToRemove);
		}
		j_BoardDefinition[row][column]=newValues;
		
		// Define parameters to undo action
		LinkedList<IntPair> cellsWithCurrentValueRemoved = new LinkedList<IntPair>();
		LinkedList<IntPair> siblings;
		// First remove value from supercell siblings
		
		
		for (int i=0;i<3;i++)
		{
			switch (i)
			{
				case 0:
					siblings=j_Utilities.GetSuperCellSiblings(row, column);
					break;
				case 1:
					siblings=j_Utilities.GetColumnSiblings(row, column);
					break;
					default:
						siblings=j_Utilities.GetRowSiblings(row, column);
			}
			// there is some duplication here but should be okay
			for (IntPair cell:siblings)
			{
				possibleValues=j_BoardDefinition[cell.GetFirst()][cell.GetSecond()];
				if (possibleValues.contains(j_SetValue))
				{
					if (possibleValues.size()==1) 
					{	
						// This means there was a contradiction.  Return an uninitialized SudokuChoiceNode
						// which will result in all the undo action being called on this method which will 
						// return the SudokuBoard to its prior state before "ResolveNode" was called
						j_ActionUndoBoardTransform = new BoardTransform(j_BoardDefinition,j_SetValue,j_CellToModify,cellsWithCurrentValueRemoved,valuesRemovedFromCurrentCell);
						return new SudokuChoiceNode(j_SudokuBoard);
					}
					possibleValues.remove(j_SetValue);
					cellsWithCurrentValueRemoved.add(new IntPair(cell.GetFirst(),cell.GetSecond()));
				}
			}
		}
		
		j_ActionUndoBoardTransform = new BoardTransform(j_BoardDefinition,j_SetValue,j_CellToModify,cellsWithCurrentValueRemoved,valuesRemovedFromCurrentCell);

		return j_SudokuBoard.GetChoiceNode();
	}

	public void Undo(){
		j_ActionUndoBoardTransform.ExecuteTransform();
	}
	
}
